package cn.drknt;

import java.io.File;
import java.io.IOException;
import java.util.Arrays;

import cn.drknt.exmpls.detector;
import cn.drknt.utls.BaseFunction;
import cn.drknt.utls.utils;

public class darknet extends BaseFunction{
	
	static {
		System.out.println("dll search path: "+System.getProperty("java.library.path"));
		System.loadLibrary("darknet_jni_wrapper");
	}
//static void average(int argc, String argv[])
//{
//    String cfgfile = argv[2];
//    String outfile = argv[3];
//    gpu_index = -1;
//    network net = parser.parse_network_cfg(cfgfile);
//    network sum = parser.parse_network_cfg(cfgfile);
//
//    String weightfile = argv[4];   
//    parser.load_weights(sum, weightfile);
//
//    int i, j;
//    int n = argc - 5;
//    for(i = 0; i < n; ++i){
//        weightfile = argv[i+5];   
//        parser.load_weights(net, weightfile);
//        for(j = 0; j < net.n; ++j){
//            layer l = net.layers[j];
//            layer out = sum.layers[j];
//            if(l.type == LAYER_TYPE.CONVOLUTIONAL){
//                int num = l.n*l.c*l.size*l.size;
//                blas.axpy_cpu(l.n, 1, l.biases, 1, out.biases, 1);
//                blas.axpy_cpu(num, 1, l.weights, 1, out.weights, 1);
//                if(l.batch_normalize){
//                	blas.axpy_cpu(l.n, 1, l.scales, 1, out.scales, 1);
//                	blas.axpy_cpu(l.n, 1, l.rolling_mean, 1, out.rolling_mean, 1);
//                	blas.axpy_cpu(l.n, 1, l.rolling_variance, 1, out.rolling_variance, 1);
//                }
//            }
//            if(l.type == LAYER_TYPE.CONNECTED){
//            	blas.axpy_cpu(l.outputs, 1, l.biases, 1, out.biases, 1);
//            	blas.axpy_cpu(l.outputs*l.inputs, 1, l.weights, 1, out.weights, 1);
//            }
//        }
//    }
//    n = n+1;
//    for(j = 0; j < net.n; ++j){
//        layer l = sum.layers[j];
//        if(l.type == LAYER_TYPE.CONVOLUTIONAL){
//            int num = l.n*l.c*l.size*l.size;
//            blas.scal_cpu(l.n, 1.f/n, l.biases, 1);
//            blas.scal_cpu(num, 1.f/n, l.weights, 1);
//                if(l.batch_normalize){
//                	blas.scal_cpu(l.n, 1.f/n, l.scales, 1);
//                    blas.scal_cpu(l.n, 1.f/n, l.rolling_mean, 1);
//                    blas.scal_cpu(l.n, 1.f/n, l.rolling_variance, 1);
//                }
//        }
//        if(l.type == LAYER_TYPE.CONNECTED){
//        	blas.scal_cpu(l.outputs, 1.f/n, l.biases, 1);
//        	blas.scal_cpu(l.outputs*l.inputs, 1.f/n, l.weights, 1);
//        }
//    }
//    parser.save_weights(sum, outfile);
//}

//void speed(String cfgfile, int tics)
//{
//    if (tics == 0) tics = 1000;
//    network net = parser.parse_network_cfg(cfgfile);
//    network.set_batch_network(net, 1);
//    int i;
//    /*time_t*/long start = time(0);
//    image im = image.make_image(net.w, net.h, net.c);
//    for(i = 0; i < tics; ++i){
//    	network.network_predict(net, im.data);
//    }
//    double t = difftime(time(0), start);
//    printf("\n%d evals, %f Seconds\n", tics, t);
//    printf("Speed: %f sec/eval\n", t/tics);
//    printf("Speed: %f Hz\n", tics/t);
//}
//double difftime(float time1, float time2) {///sjx
//	return time1-time2;
//}
//void operations(String cfgfile)
//{
//    gpu_index = -1;
//    network net = parser.parse_network_cfg(cfgfile);
//    int i;
//    long ops = 0;
//    for(i = 0; i < net.n; ++i){
//        layer l = net.layers[i];
//        if(l.type == LAYER_TYPE.CONVOLUTIONAL){
//            ops += 2l * l.n * l.size*l.size*l.c * l.out_h*l.out_w;
//        } else if(l.type == LAYER_TYPE.CONNECTED){
//            ops += 2l * l.inputs * l.outputs;
//        }
//    }
//    printf("Floating Point Operations: %ld\n", ops);
//    printf("Floating Point Operations: %.2f Bn\n", (float)ops/1000000000.);
//}
//
//void oneoff(String cfgfile, String weightfile, String outfile)
//{
//    gpu_index = -1;
//    network net = parser.parse_network_cfg(cfgfile);
//    int oldn = net.layers[net.n - 2].n;
//    int c = net.layers[net.n - 2].c;
//    net.layers[net.n - 2].n = 9372;
//    net.layers[net.n - 2].biases += 5;
//    net.layers[net.n - 2].weights += 5*c;
//    if(weightfile!=null){
//        parser.load_weights(net, weightfile);
//    }
//    net.layers[net.n - 2].biases -= 5;
//    net.layers[net.n - 2].weights -= 5*c;
//    net.layers[net.n - 2].n = oldn;
//    printf("%d\n", oldn);
//    layer l = net.layers[net.n - 2];
//    blas.copy_cpu(l.n/3, l.biases, 1, l.biases +   l.n/3, 1);
//    blas.copy_cpu(l.n/3, l.biases, 1, l.biases + 2*l.n/3, 1);
//    blas.copy_cpu(l.n/3*l.c, l.weights, 1, l.weights +   l.n/3*l.c, 1);
//    blas.copy_cpu(l.n/3*l.c, l.weights, 1, l.weights + 2*l.n/3*l.c, 1);
//    net.seen[0] = 0;
//    parser.save_weights(net, outfile);
//}
//
//void partial(String cfgfile, String weightfile, String outfile, int max)
//{
//    gpu_index = -1;
//    network net = parser.parse_network_cfg(cfgfile);
//    if(weightfile!=null){
//        parser.load_weights_upto(net, weightfile, max);
//    }
//    net.seen[0] = 0;
//    parser.save_weights_upto(net, outfile, max);
//}
//
////#include "convolutional_layer.h"
//void rescale_net(String cfgfile, String weightfile, String outfile)
//{
//    gpu_index = -1;
//    network net = parser.parse_network_cfg(cfgfile);
//    if(weightfile!=null){
//        parser.load_weights(net, weightfile);
//    }
//    int i;
//    for(i = 0; i < net.n; ++i){
//        layer l = net.layers[i];
//        if(l.type == LAYER_TYPE.CONVOLUTIONAL){
//            rescale_weights(l, 2, -.5);
//            break;
//        }
//    }
//    parser.save_weights(net, outfile);
//}
//
//void rgbgr_net(String cfgfile, String weightfile, String outfile)
//{
//    gpu_index = -1;
//    network net = parser.parse_network_cfg(cfgfile);
//    if(weightfile!=null){
//        parser.load_weights(net, weightfile);
//    }
//    int i;
//    for(i = 0; i < net.n; ++i){
//        layer l = net.layers[i];
//        if(l.type == LAYER_TYPE.CONVOLUTIONAL){
//            rgbgr_weights(l);
//            break;
//        }
//    }
//    parser.save_weights(net, outfile);
//}
//
//void reset_normalize_net(String cfgfile, String weightfile, String outfile)
//{
//    gpu_index = -1;
//    network net = parser.parse_network_cfg(cfgfile);
//    if (weightfile!=null) {
//        parser.load_weights(net, weightfile);
//    }
//    int i;
//    for (i = 0; i < net.n; ++i) {
//        layer l = net.layers[i];
//        if(l.type == LAYER_TYPE.CONVOLUTIONAL && l.batch_normalize) {
//            denormalize_convolutional_layer(l);
//        }
//        if(l.type == LAYER_TYPE.CONNECTED && l.batch_normalize) {
//            denormalize_connected_layer(l);
//        }
//        if(l.type == LAYER_TYPE.GRU && l.batch_normalize) {
//            denormalize_connected_layer(l.input_z_layer);
//            denormalize_connected_layer(l.input_r_layer);
//            denormalize_connected_layer(l.input_h_layer);
//            denormalize_connected_layer(l.state_z_layer);
//            denormalize_connected_layer(l.state_r_layer);
//            denormalize_connected_layer(l.state_h_layer);
//        }
//    }
//    parser.save_weights(net, outfile);
//}
//
//layer normalize_layer(layer l, int n)
//{
//    int j;
//    l.batch_normalize=1;
//    l.scales = calloc(n, 1/*sizeof(float)*/);
//    for(j = 0; j < n; ++j){
//        l.scales[j] = 1;
//    }
//    l.rolling_mean = calloc(n, 1/*sizeof(float)*/);
//    l.rolling_variance = calloc(n, 1/*sizeof(float)*/);
//    return l;
//}
//
//void normalize_net(String cfgfile, String weightfile, String outfile)
//{
//    gpu_index = -1;
//    network net = parser.parse_network_cfg(cfgfile);
//    if(weightfile!=null){
//        parser.load_weights(net, weightfile);
//    }
//    int i;
//    for(i = 0; i < net.n; ++i){
//        layer l = net.layers[i];
//        if(l.type == LAYER_TYPE.CONVOLUTIONAL && l.batch_normalize==0){
//            net.layers[i] = normalize_layer(l, l.n);
//        }
//        if(l.type == LAYER_TYPE.CONNECTED && l.batch_normalize==0) {
//            net.layers[i] = normalize_layer(l, l.outputs);
//        }
//        if(l.type == LAYER_TYPE.GRU && l.batch_normalize) {
//            l.input_z_layer = normalize_layer(l.input_z_layer, l.input_z_layer.outputs);
//            l.input_r_layer = normalize_layer(l.input_r_layer, l.input_r_layer.outputs);
//            l.input_h_layer = normalize_layer(l.input_h_layer, l.input_h_layer.outputs);
//            l.state_z_layer = normalize_layer(l.state_z_layer, l.state_z_layer.outputs);
//            l.state_r_layer = normalize_layer(l.state_r_layer, l.state_r_layer.outputs);
//            l.state_h_layer = normalize_layer(l.state_h_layer, l.state_h_layer.outputs);
//            net.layers[i].batch_normalize=1;
//        }
//    }
//    parser.save_weights(net, outfile);
//}
//
//void statistics_net(String cfgfile, String weightfile)
//{
//    gpu_index = -1;
//    network net = parser.parse_network_cfg(cfgfile);
//    if (weightfile!=null) {
//        parser.load_weights(net, weightfile);
//    }
//    int i;
//    for (i = 0; i < net.n; ++i) {
//        layer l = net.layers[i];
//        if(l.type == LAYER_TYPE.CONNECTED && l.batch_normalize) {
//            printf("Connected Layer %d\n", i);
//            statistics_connected_layer(l);
//        }
//        if(l.type == LAYER_TYPE.GRU && l.batch_normalize) {
//            printf("GRU Layer %d\n", i);
//            printf("Input Z\n");
//            statistics_connected_layer(l.input_z_layer);
//            printf("Input R\n");
//            statistics_connected_layer(l.input_r_layer);
//            printf("Input H\n");
//            statistics_connected_layer(l.input_h_layer);
//            printf("State Z\n");
//            statistics_connected_layer(l.state_z_layer);
//            printf("State R\n");
//            statistics_connected_layer(l.state_r_layer);
//            printf("State H\n");
//            statistics_connected_layer(l.state_h_layer);
//        }
//        printf("\n");
//    }
//}
//
//void denormalize_net(String cfgfile, String weightfile, String outfile)
//{
//    gpu_index = -1;
//    network net = parser.parse_network_cfg(cfgfile);
//    if (weightfile!=null) {
//    	parser.load_weights(net, weightfile);
//    }
//    int i;
//    for (i = 0; i < net.n; ++i) {
//        layer l = net.layers[i];
//        if(l.type == LAYER_TYPE.CONVOLUTIONAL && l.batch_normalize) {
//            denormalize_convolutional_layer(l);
//            net.layers[i].batch_normalize=0;
//        }
//        if(l.type == LAYER_TYPE.CONNECTED && l.batch_normalize) {
//            denormalize_connected_layer(l);
//            net.layers[i].batch_normalize=false;
//        }
//        if(l.type == LAYER_TYPE.GRU && l.batch_normalize) {
//            denormalize_connected_layer(l.input_z_layer);
//            denormalize_connected_layer(l.input_r_layer);
//            denormalize_connected_layer(l.input_h_layer);
//            denormalize_connected_layer(l.state_z_layer);
//            denormalize_connected_layer(l.state_r_layer);
//            denormalize_connected_layer(l.state_h_layer);
//            l.input_z_layer.batch_normalize = false;
//            l.input_r_layer.batch_normalize = false;
//            l.input_h_layer.batch_normalize = false;
//            l.state_z_layer.batch_normalize = false;
//            l.state_r_layer.batch_normalize = false;
//            l.state_h_layer.batch_normalize = false;
//            net.layers[i].batch_normalize=false;
//        }
//    }
//    parser.save_weights(net, outfile);
//}

//void visualize(String cfgfile, String weightfile)
//{
//    network net = parser.parse_network_cfg(cfgfile);
//    if(weightfile!=null){
//    	parser.load_weights(net, weightfile);
//    }
//    visualize_network(net);
////#ifdef OPENCV
////    cvWaitKey(0);
////#endif
//}
private static String[] setParams(  ) {
	String[] args=new String[4];
	int i=0;
	args[i++]="detector";
	args[i++]="train";
	args[i++]="face.data";
	args[i++]="yolo-face.cfg";

	System.err.println("THIS IS DEMO : "+Arrays.toString(args));
	return args;
}
public static void main(String[] args) throws IOException,Exception{
	if(args.length<2) {
		args=setParams( );
	}else{
		System.err.println("PARAM FROM OUTSIDE : "+Arrays.toString(args));
	}
	System.out.println("pwd: "+new File("").getAbsolutePath());
	String[] argv=new String[args.length+1];
	System.arraycopy(args, 0, argv, 1, args.length);
	int argc=argv.length;

    //test_resize("data/bad.jpg");
    //test_box();
    //test_convolutional_layer();
    if(argc < 2){
        fprintf(stderr, "usage: %s <function>\n", argv[0]);
        return;
    }
    gpu_index = utils.find_int_arg(argc, argv, "-i", 0);
    if(utils.find_arg(argc, argv, "-nogpu")) {
        gpu_index = -1;
    }

//#ifndef GPU
    gpu_index = -1;
//#else
//    if(gpu_index >= 0){
//        cuda_set_device(gpu_index);
//    }
//#endif

//    if (0 == strcmp(argv[1], "average")){
//        average(argc, argv);
//    } else if (0 == strcmp(argv[1], "yolo")){
//        run_yolo(argc, argv);
//    } else if (0 == strcmp(argv[1], "voxel")){
//        run_voxel(argc, argv);
//    } else if (0 == strcmp(argv[1], "super")){
//        run_super(argc, argv);
//    } else 
    if (0 == strcmp(argv[1], "detector")){
    	new detector().run_detector(argc, argv);
    } 
//    else if (0 == strcmp(argv[1], "detect")){
//        float thresh = find_float_arg(argc, argv, "-thresh", .24);
//        String filename = (argc > 4) ? argv[4]: 0;
//        test_detector("cfg/coco.data", argv[2], argv[3], filename, thresh);
//    } else if (0 == strcmp(argv[1], "cifar")){
//        run_cifar(argc, argv);
//    } else if (0 == strcmp(argv[1], "go")){
//        run_go(argc, argv);
//    } else if (0 == strcmp(argv[1], "rnn")){
//        run_char_rnn(argc, argv);
//    } else if (0 == strcmp(argv[1], "vid")){
//        run_vid_rnn(argc, argv);
//    } else if (0 == strcmp(argv[1], "coco")){
//        run_coco(argc, argv);
//    } else if (0 == strcmp(argv[1], "classify")){
//        predict_classifier("cfg/imagenet1k.data", argv[2], argv[3], argv[4], 5);
//    } else if (0 == strcmp(argv[1], "classifier")){
//        run_classifier(argc, argv);
//    } else if (0 == strcmp(argv[1], "art")){
//        run_art(argc, argv);
//    } else if (0 == strcmp(argv[1], "tag")){
//        run_tag(argc, argv);
//    } else if (0 == strcmp(argv[1], "compare")){
//        run_compare(argc, argv);
//    } else if (0 == strcmp(argv[1], "dice")){
//        run_dice(argc, argv);
//    } else if (0 == strcmp(argv[1], "writing")){
//        run_writing(argc, argv);
//    } else if (0 == strcmp(argv[1], "3d")){
//        composite_3d(argv[2], argv[3], argv[4], (argc > 5) ? atof(argv[5]) : 0);
//    } else if (0 == strcmp(argv[1], "test")){
//        test_resize(argv[2]);
//    } else if (0 == strcmp(argv[1], "captcha")){
//        run_captcha(argc, argv);
//    } else if (0 == strcmp(argv[1], "nightmare")){
//        run_nightmare(argc, argv);
//    } else if (0 == strcmp(argv[1], "rgbgr")){
//        rgbgr_net(argv[2], argv[3], argv[4]);
//    } else if (0 == strcmp(argv[1], "reset")){
//        reset_normalize_net(argv[2], argv[3], argv[4]);
//    } else if (0 == strcmp(argv[1], "denormalize")){
//        denormalize_net(argv[2], argv[3], argv[4]);
//    } else if (0 == strcmp(argv[1], "statistics")){
//        statistics_net(argv[2], argv[3]);
//    } else if (0 == strcmp(argv[1], "normalize")){
//        normalize_net(argv[2], argv[3], argv[4]);
//    } else if (0 == strcmp(argv[1], "rescale")){
//        rescale_net(argv[2], argv[3], argv[4]);
//    } else if (0 == strcmp(argv[1], "ops")){
//        operations(argv[2]);
//    } else if (0 == strcmp(argv[1], "speed")){
//        speed(argv[2], (argc > 3 && argv[3]) ? atoi(argv[3]) : 0);
//    } else if (0 == strcmp(argv[1], "oneoff")){
//        oneoff(argv[2], argv[3], argv[4]);
//    } else if (0 == strcmp(argv[1], "partial")){
//        partial(argv[2], argv[3], argv[4], atoi(argv[5]));
//    } else if (0 == strcmp(argv[1], "average")){
//        average(argc, argv);
//    } else if (0 == strcmp(argv[1], "visualize")){
//        visualize(argv[2], (argc > 3) ? argv[3] : 0);
//    } else if (0 == strcmp(argv[1], "imtest")){
//        test_resize(argv[2]);
//    } 
    else {
        fprintf(stderr, "Not an option: %s\n", argv[1]);
    }
    return;
}
}
